package src;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.lang.Error;
class Node{
    volatile Thread thread;
    volatile Node next;             //链表队列的可见性维护
    public Node(Thread t){
        thread = t;
    }
    public String toString(){
        return String.format("线程:%S,next指向=>%s",thread.toString(), next);
    }
}
/**
 * 自定义实现一个排他锁
 * 
 */
public class TinyLock {
    //1.共享状态
    private volatile int state = 1;
    private volatile Node head;
    private volatile Node tail;
    private static final Unsafe unsafe = getUnsafeInstance();
    //2.CAS原子操作
    private static final long stateOffset;
    private static final long headOffset;
    private static final long tailOffset;
    private static final long ownerOffset;
    private static final long holdCountOffset;
    static{
        try{
            stateOffset = unsafe.objectFieldOffset(TinyLock.class.getDeclaredField("state"));
            headOffset = unsafe.objectFieldOffset(TinyLock.class.getDeclaredField("head"));
            tailOffset = unsafe.objectFieldOffset(TinyLock.class.getDeclaredField("tail"));
            ownerOffset = unsafe.objectFieldOffset(TinyLock.class.getDeclaredField("owner"));
            holdCountOffset = unsafe.objectFieldOffset(TinyLock.class.getDeclaredField("holdCount"));
        }catch(Exception ex){
            throw new Error(ex);
        }
    }
    //3.添加ReentrantLock相关实现
    private volatile Thread owner = null;
    private volatile int holdCount = 0;
    public int getHoldCount(){
        return this.holdCount;
    }
    public void lock(){
        Thread t = Thread.currentThread();
        //System.out.printf("【Lock】当前线程尝试获锁:%s\n",t);
        if(t==owner){
            holdCount++;
            return;
        }
        for(;;){
            /**
             * 并发操作时变量操作规则：
             * 1.读取时volatile直接从内存读
             * 2.写入时需要使用操作系统底层提供的原子操作能力
             * */
            if(state>0){
                //int newState = state-1; XX 这样的操作不可取，CAS的操作参数在进行操作前要显式确定
                if(state>0&&unsafe.compareAndSwapInt(this, stateOffset, 1, 0)){
                    //System.out.println("变量state-1");
                    boolean setFlag = unsafe.compareAndSwapObject(this,ownerOffset,null,t);
                    if(!setFlag){
                        System.out.println("owne写入未成功！");
                    }
                    while(!setFlag){
                        setFlag = unsafe.compareAndSwapObject(this,ownerOffset,null,t);
                    }
                    setFlag = unsafe.compareAndSwapInt(this,holdCountOffset,0,1);
                    while(!setFlag){
                        setFlag = unsafe.compareAndSwapInt(this,holdCountOffset,0,1);
                    }
                    //unsafe.storeFence();
                    return;
                } 
            }else{
                //挂起当前线程，加入等待队列
                //park(boolean isAbsolute long time)
                enq(t);
                //加入队列之后，可能存在被唤醒的情况
                if(state>0&&owner!=t){
                    continue;
                }
                unsafe.park(false, 0L);
            }
        }
    }
    /**
     * 多个线程可能同时操作等待队列，所以此处需要原子化操作
     * @return
     */
    public void enq(Thread t){
        Node curNode = new Node(t);
        Node preNode = null;
        for(;;){
            //1.队头为空，插入队头
            if(head==null){
                if(unsafe.compareAndSwapObject(this, headOffset, null, curNode)){
                    tail = curNode;
                    return;
                }
            }else{
                //2.队头不为空，插入队尾    
                preNode = tail;
                /**
                 * 修改原tail为preNode来让本地副本与内存空间变量之间保持一致性
                 * 这个地方在测试过程中出现NPE
                 * */
                if(preNode!=null&&unsafe.compareAndSwapObject(this, tailOffset, preNode,curNode)){
                    preNode.next = curNode;
                    return;
                }
            }
        }

    }
    public void release(){
        Thread t = Thread.currentThread();
        unsafe.loadFence();
        if(owner!=t){
            System.out.printf("异常情况输出,owner:%s,t:%s",owner,t);
            throw new IllegalMonitorStateException("不是锁的持有者！");
        }
        holdCount--;
        if(holdCount>0){
            return;
        }
        //此时线程是持有锁的
        if(state!=0){
            throw new IllegalMonitorStateException("互斥变量状态一致性异常!");
        }
        for(;;){
            if(state==0&&unsafe.compareAndSwapInt(this, stateOffset, 0, 1)){
                boolean setFlag = unsafe.compareAndSwapObject(this,ownerOffset,t,null);
                if(!setFlag){
                    throw new IllegalMonitorStateException("owne释放未成功！");
                }
                while(!setFlag){
                    setFlag = unsafe.compareAndSwapObject(this,ownerOffset,t,null);
                }
                /**
                 * 通过内存屏障，保证state与owner的一致性
                 * 否则其它线程解锁时会提示不是锁的持有者
                 * */
                unsafe.storeFence();  
                //1.唤醒接下来的线程，队头为空，无唤醒Node
                if(head==null){
                    //System.out.println("TinyLock，队头为空\n");
                }else{
                    //2.唤醒队头的线程
                    Node ptr = head;
                    head = ptr.next;
                    ptr.next = null;    //显式清理引用
                    //System.out.printf("TinyLock，队头不为空，解锁：%s\n",ptr);
                    if(head==null){
                        tail = null;
                    }
                    unsafe.unpark(ptr.thread);
                }
                return;
            }
        }   
    }

    private static Unsafe getUnsafeInstance() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
            } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
